home *** CD-ROM | disk | FTP | other *** search
/ PD ROM 1 / PD ROM Volume I - Macintosh Software from BMUG (1988).iso / Stacks / Updates⁄New / TEXAS for BMUG / C progs / TEXAS XFCNs ƒ / getKeysXFCN.1.c < prev    next >
Encoding:
C/C++ Source or Header  |  1987-11-29  |  4.7 KB  |  219 lines  |  [TEXT/KAHL]

  1. /* HyperCard XFCN that returns the M index key items found beginning at
  2.  * key record number N in (already opened) key file F ... called as:
  3.  *    getKeys ( M, N, F)
  4.  * where N is 0-based, and F is a refNum value returned by
  5.  * the XFCN openFile() ....
  6.  *
  7.  * The results are returned as a nice printable string consisting of M
  8.  * repetitions of:
  9.  *   the number of occurrences of the item, ranging from 1 up to at
  10.  *      most 999999 (MAX_DIGITS long ... 6 is a nice choice), followed by;
  11.  *   a space, to separate the columns, followed by;
  12.  *   the item's key word, KEY_LENGTH characters long, padded on the right
  13.  *      by trailing blanks as necessary, followed by;
  14.  *   a <return>.
  15.  * If there has been a mistake, a null string is returned and the function
  16.  * also emits a beep....
  17.  *
  18.  * Function is stored as XFCN number 270, named "getKeys"....
  19.  *
  20.  * The key file must in the standard ^z browser format as created
  21.  * by qndxr....
  22.  *
  23.  * 871126 ^z
  24.  */
  25.  
  26. #include <MacTypes.h>
  27. #include <FileMgr.h>
  28. #include <OSUtil.h>
  29. #include <HyperXCmd.h>
  30. #include <proto.h>
  31.  
  32. #define KEY_LENGTH  28            /* depends on how index file was built */
  33. #define MAX_DIGITS   6            /* chosen field width for counts */
  34. #define MAX_COUNT  999999        /* biggest decimal number in MAX_DIGITS */
  35. typedef struct
  36.   {
  37.     char kkey[KEY_LENGTH];
  38.     long ccount;
  39.   }  KEY_REC;
  40.  
  41.  
  42. pascal void main (XCmdBlockPtr paramPtr);
  43. void getKeyRec (KEY_REC *recp, long recNum, int refNum);
  44. void buildAnswer (char *ans, long count, char *key);
  45. void storeNum (char *ans, long count);
  46. void complain (XCmdBlockPtr paramPtr);
  47.  
  48.  
  49. pascal void main (paramPtr)
  50.   XCmdBlockPtr paramPtr;
  51.   {
  52.     KEY_REC this_rec, prev_rec;
  53.     int refNum0, keys, i;
  54.     long indexRecNum;
  55.     Handle answer;
  56.     
  57.     if (paramPtr->paramCount != 3)
  58.       {
  59.           complain(paramPtr);
  60.           return;
  61.       }
  62.      
  63.     keys = atol (*(paramPtr->params[0]));
  64.     indexRecNum = atol (*(paramPtr->params[1]));
  65.     refNum0 = atol (*(paramPtr->params[2]));
  66.     
  67.     if (indexRecNum < 0 || refNum0 == 0)
  68.       {
  69.           complain (paramPtr);
  70.           return;
  71.       }
  72.     
  73.     answer = NewHandle (keys * (MAX_DIGITS + KEY_LENGTH + 2) + 1);
  74.     getKeyRec (&prev_rec, indexRecNum - 1, refNum0);
  75.     
  76.     for (i = 0; i < keys; ++i)
  77.       {
  78.         getKeyRec (&this_rec, indexRecNum++, refNum0);
  79.         buildAnswer (*answer + i * (MAX_DIGITS + KEY_LENGTH + 2),
  80.                     this_rec.ccount - prev_rec.ccount, this_rec.kkey);
  81.         prev_rec.ccount = this_rec.ccount;
  82.       }
  83.     
  84.     *(*answer + keys * (MAX_DIGITS + KEY_LENGTH + 2)) = '\0';
  85.     paramPtr->returnValue = answer;
  86.     return;
  87.   }
  88.  
  89.  
  90. /* function to fetch the requested index record from the file ...
  91.  * note that if an illegal recNum is asked for, it
  92.  * returns 0 for ccount and a blank kkey....
  93.  */
  94.  
  95. void getKeyRec (recp, recordNum, refNum)
  96.   KEY_REC *recp;
  97.   long recordNum;
  98.   int refNum;
  99.   {
  100.     long count;
  101.     int i;
  102.  
  103.     count = sizeof(KEY_REC);
  104.             
  105.     if (recordNum < 0 ||
  106.             SetFPos (refNum, fsFromStart, 
  107.                     recordNum * sizeof(KEY_REC)) != noErr ||
  108.             FSRead (refNum, &count, recp) != noErr)
  109.       {
  110.         for (i = 0; i < KEY_LENGTH; ++i)
  111.             recp->kkey[i] = ' ';
  112.           recp->ccount = 0;
  113.       }
  114.  
  115.     return;
  116.   }
  117.  
  118.  
  119. /* function to format the index record nicely as a string .... 
  120.  * put the count in its proper place  (signal an overflow by
  121.  * filling its field with stars), followed by a space, then
  122.  * the key word itself, followed by a <return>....
  123.  */
  124.  
  125. void buildAnswer (ans, count, key)
  126.   register char *ans, *key;
  127.   long count;
  128.   {
  129.     register int i;
  130.     
  131.     if (count > MAX_COUNT)
  132.         for (i = MAX_DIGITS; i > 0; --i)
  133.             *ans++ = '*';
  134.     else
  135.       {
  136.         storeNum (ans, count);
  137.         ans += MAX_DIGITS;
  138.       }
  139.  
  140.     *ans++ = ' ';
  141.     
  142.     for (i = KEY_LENGTH; i > 0; --i)
  143.         *ans++ = *key++;
  144.     
  145.     *ans = '\r';
  146.     
  147.     return;
  148.   }
  149.  
  150.  
  151. /* function to convert a number into a string of width MAX_DIGITS and
  152.  * store it right-justified, blank-filled on left; assume that the
  153.  * number is non-negative and is less than or equal to MAX_DIGITS
  154.  * long in decimal.... based on K&R p. 60 example of itoa()....
  155.  */
  156.  
  157. void storeNum (ans, count)
  158.   register char *ans;
  159.   register long count;
  160.   {
  161.     register int i;
  162.     
  163.     i = MAX_DIGITS - 1;
  164.     
  165.     do
  166.           ans[i--] = count % 10 + '0';
  167.     while ((count /= 10) > 0);
  168.     
  169.     for ( ; i >= 0; --i)
  170.         ans[i] = ' ';
  171.  
  172.     return;
  173.   }
  174.   
  175.  
  176. /* function to beep and set the return string to null (= "")
  177.  */
  178.  
  179. void complain (paramPtr)
  180.   XCmdBlockPtr paramPtr;
  181.   {
  182.     Handle answer;
  183.     
  184.       SysBeep (10);
  185.     answer = NewHandle (1);
  186.     **answer = '\0';
  187.     paramPtr->returnValue = answer;
  188.     return;
  189.   }
  190.  
  191.  
  192.  
  193. /* function to convert alphabetic string to a long integer ... from LSC
  194.  * library.... simplified to avoid using isspace() & isdigit() .... */
  195.  
  196. long atol (s)
  197.   register char *s;
  198.   {
  199.     register char signflag = 0;
  200.     register long r = 0;
  201.  
  202.     while ((*s == ' '))
  203.         s++;
  204.         
  205.     if (*s == '-')
  206.       {
  207.         signflag = 1;
  208.         s++;
  209.       }
  210.     else if (*s == '+')
  211.          s++;
  212.  
  213.     while (*s >= '0' && *s <= '9') 
  214.         r = r * 10 + (*s++ - '0');
  215.     
  216.     return (signflag ? -r : r);
  217. }
  218.  
  219.